/*
 *    This file is part of BlobDB.
 *
 *    BlobDB is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    BlobDB is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with BlobDB.  If not, see <http://www.gnu.org/licenses/>.
 *    
 *    Copyright(c) 2011 Michael Kankkonen
 *    http://www.vnetcon.org
 */


package org.vnetcon.blobdb.database;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;

import org.vnetcon.blobdb.database.util.ColumnInfo;
import org.vnetcon.blobdb.database.util.SQLParser;

/**
 * This is the class where BlobDB stores the data after finding it from back end
 * "data blobs".
 * 
 * If you use BlobDB directly from java code you will never see this class but if
 * you have generated the WebService client side classes against BlobDB WebService then
 * you will get all the row data from these classes.
 *
 */
public class Result implements Comparable<Result>{

	Hashtable<String, String> columnValues;
	ArrayList<ResultSet> subqueries = new ArrayList<ResultSet>();
	List<String[]> orderBy = null;
	List<String> selectCols = new ArrayList<String>();
	StringBuilder sb = new StringBuilder();
	
	byte[] rowData = null;
	ColumnInfo colInfo = null;
	boolean ignoreCase = false;
	String rowid = null;
	
	public Result(){
		columnValues = new Hashtable<String, String>();
		subqueries = new ArrayList<ResultSet>();
	}

	public void finalize(){
		columnValues = null;
		subqueries = null;
		orderBy = null;
		selectCols = null;
		rowData = null;
		colInfo = null;
		Runtime.getRuntime().gc();
	}
	
	
	/**
	 * Used by BlobDB
	 * 
	 * @param rowid
	 */
	public void setRowid(String rowid){
		this.rowid = rowid;
	}
	
	public String getRowid(){
		return this.rowid;
	}

	/**
	 * This one is here for sorting reasons.
	 * 
	 * @param ignore
	 */
	public void setIgnoreCase(boolean ignore){
		this.ignoreCase = ignore;
	}

	/**
	 * Used by BlobDB
	 * 
	 * @param selectCols
	 */
	public void setSelectCols(List<String> selectCols){
		this.selectCols = selectCols;
	}

	/**
	 * Used by BlobDB. With this method BlobDB will set the sort order
	 * parsed form sql's "order by" section.
	 * 
	 * @param orderBy
	 */
	public void setOrderBy(List<String[]> orderBy){
		this.orderBy = orderBy;
	}

	/**
	 * Used by BlobDB.
	 * 
	 * @param rowdata
	 * @param ci
	 */
	public void setRawData(byte[] rowdata, ColumnInfo ci){
		this.rowData = rowdata;
		this.colInfo = ci;
	}

	/**
	 * This Hashtable if for WebSrvice clients to get result values mapped with column names.
	 * 
	 * @return
	 */
	public Hashtable<String, String> getColumnValues() {
		return columnValues;
	}

	/**
	 * Used by BlobDB
	 * 
	 * @param columnValues
	 */
	public void setColumnValues(Hashtable<String, String> columnValues) {
		this.columnValues = columnValues;
	}

	/**
	 * This is for WebService clients so they can also retrieve sub select values.
	 * 
	 * @return
	 */
	public ArrayList<ResultSet> getSubqueries() {
		return subqueries;
	}

	/**
	 * Used by BlobDB
	 * 
	 * @param subqueries
	 */
	public void setSubqueries(ArrayList<ResultSet> subqueries) {
		this.subqueries = subqueries;
	}

	/**
	 * This for java sort. 
	 * 
	 */
	@Override
	public int compareTo(Result cmp) {
		String A = null;
		String B = null;
		String colToCompare = null;
		int iRet = 0;
		int i = 0;
		
		if(this.orderBy.size() == 0){
			String buf[] = new String[2];
			colToCompare = this.selectCols.get(0);
			buf[0] = colToCompare;
			buf[1] = SQLParser.ORDER_DESC;
			this.orderBy.add(buf);
		}
		
		while(i < this.orderBy.size()){
			String buf[] = this.orderBy.get(i);
			A = this.getColumnValues().get(buf[0]);
			B = cmp.getColumnValues().get(buf[0]);
			
			if(buf[1].equals(SQLParser.ORDER_DESC)){
				if(!ignoreCase){
					iRet = A.compareTo(B);
				}else{
					iRet = A.compareToIgnoreCase(B);
				}
			}else{
				if(!ignoreCase){
					iRet = B.compareTo(A);
				}else{
					iRet = B.compareToIgnoreCase(A);
				}
			}
			
			if(iRet != 0){
				break;
			}
			
			i++;
		}

		return iRet;
	}
	

	public StringBuilder toXML(){
		int i = 0;
		Enumeration<String> e = this.columnValues.keys();
		sb.append("<columnValues>");
		
		while(e.hasMoreElements()){
			String key = e.nextElement();
			if(this.selectCols.contains(key)){
				sb.append("<entry>");
				sb.append("<key>");
				sb.append(key);
				sb.append("</key>");
				sb.append("<value>");
				sb.append(this.columnValues.get(key));
				sb.append("</value>");
				sb.append("</entry>");
			}
		}		
		sb.append("</columnValues>");
		if(this.subqueries.size() > 0){
			sb.append("<subqueries>");
			while (i < this.subqueries.size()) {
				sb.append(this.subqueries.get(i).toXML());
				i++;
			}
			sb.append("</subqueries>");
		}
		return sb;
	}
	
}
